package com.wtx.security.filter;

import com.alibaba.fastjson.JSON;
import com.wtx.security.common.RedisConstants;
import com.wtx.security.common.RedisService;
import com.wtx.security.common.ResponseResult;
import com.wtx.security.util.JwtUtil;
import com.wtx.security.util.PermissionUtil;
import com.wtx.security.util.ResponseUtil;
import com.wtx.security.vo.SysUserVO;
import lombok.SneakyThrows;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token验证过滤器
 */
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private RedisService redisService;

    public TokenAuthenticationFilter(RedisService redisService) {
        this.redisService = redisService;
    }


    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
//        logger.info("uri:" + request.getRequestURI());
//        //如果是登录类接口，直接放行
        if (request.getRequestURI().startsWith("/admin/login")) {
            chain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(request, response);
        if (null != authentication) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request, response);
        }

    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //token置于header里
        String token = request.getHeader("token");
//        logger.info("token:" + token);
        String userId = null;
        if (!StringUtils.hasText(token)) {
            ResponseUtil.out(response, new ResponseResult(403, "token不能为空"));
            return null;
        }
        try {
            userId = JSON.parseObject(JwtUtil.parseJWT(token).getSubject(), String.class);
        } catch (Exception e) {
            logger.error("解析token失败:", e);
            ResponseUtil.out(response, new ResponseResult(403, "非法的token"));
            return null;
        }
        String userStr = redisService.getStringRedisTemplate().opsForValue().get(String.format(RedisConstants.USER_KEY_TEMPLATE, userId));
        if (!StringUtils.hasText(userStr)) {
            ResponseUtil.out(response, new ResponseResult(403, "登录已失效,请重新登录"));
            return null;
        }
        SysUserVO sysUserVO = JSON.parseObject(userStr, SysUserVO.class);
        return new UsernamePasswordAuthenticationToken(sysUserVO, null, PermissionUtil.getAuthorities(sysUserVO.getPermissionList()));
    }
}
